/*---------------------------------------------------------------------
 * File name: hal_spi.cpp
 *
 * Copyright (c) <2020-2022>, <ChenLong>
 *
 * All rights reserved.
 *
 * Author: ChenLong
 * Email: worldlong@foxmail.com
 *--------------------------------------------------------------------*/
#include "gd32f30x.h"
#include "hal_spi.h"
#include "hal_config.h"
#if defined(USING_RT_THREAD)
#include "rtthread.h" 
#endif
/*
*/
//SPI0
#if SPI0_ENABLE
#if SPI0_RX_DMA_ENABLE
#if SPI0_RX_DMA == DMA0_CHANNEL1
#define SPI0_RX_DMA_PORT    DMA0
#define SPI0_RX_DMA_CH      DMA_CH1
#define SPI0_RX_DMA_CH_IRQN DMA0_Channel1_IRQn
#define SPI0_RX_DMA_CH_IRQH DMA0_Channel1_IRQHandler
#else
#error "SPI0_RX_DMA incorrect."
#endif
#else
#define SPI0_RX_DMA_PORT 0
#define SPI0_RX_DMA_CH   0
#endif
#if SPI0_TX_DMA_ENABLE
#if SPI0_TX_DMA == DMA0_CHANNEL2
#define SPI0_TX_DMA_PORT    DMA0
#define SPI0_TX_DMA_CH      DMA_CH2
#define SPI0_TX_DMA_CH_IRQN DMA0_Channel2_IRQn
#define SPI0_TX_DMA_CH_IRQH DMA0_Channel2_IRQHandler
#else
#error "SPI0_TX_DMA incorrect."
#endif
#else
#define SPI0_TX_DMA_PORT 0
#define SPI0_TX_DMA_CH   0
#endif
#endif
//SPI1
#if SPI1_ENABLE
#if SPI1_RX_DMA_ENABLE
#if SPI1_RX_DMA == DMA0_CHANNEL3
#define SPI1_RX_DMA_PORT    DMA0
#define SPI1_RX_DMA_CH      DMA_CH3
#define SPI1_RX_DMA_CH_IRQN DMA0_Channel3_IRQn
#define SPI1_RX_DMA_CH_IRQH DMA0_Channel3_IRQHandler
#else
#error "SPI1_RX_DMA incorrect."
#endif
#else
#define SPI1_RX_DMA_PORT 0
#define SPI1_RX_DMA_CH   0
#endif
#if SPI1_TX_DMA_ENABLE
#if SPI1_TX_DMA == DMA0_CHANNEL4
#define SPI1_TX_DMA_PORT    DMA0
#define SPI1_TX_DMA_CH      DMA_CH4
#define SPI1_TX_DMA_CH_IRQN DMA0_Channel4_IRQn
#define SPI1_TX_DMA_CH_IRQH DMA0_Channel4_IRQHandler
#else
#error "SPI1_TX_DMA incorrect."
#endif
#else
#define SPI1_TX_DMA_PORT 0
#define SPI1_TX_DMA_CH   0
#endif
#endif
//SPI2
#if SPI2_ENABLE
#if SPI2_RX_DMA_ENABLE
#if SPI2_RX_DMA == DMA1_CHANNEL0
#define SPI2_RX_DMA_PORT    DMA1
#define SPI2_RX_DMA_CH      DMA_CH0
#define SPI2_RX_DMA_CH_IRQN DMA1_Channel0_IRQn
#define SPI2_RX_DMA_CH_IRQH DMA1_Channel0_IRQHandler
#else
#error "SPI2_RX_DMA incorrect."
#endif
#else
#define SPI2_RX_DMA_PORT 0
#define SPI2_RX_DMA_CH   0
#endif
#if SPI2_TX_DMA_ENABLE
#if SPI2_TX_DMA == DMA1_CHANNEL1
#define SPI2_TX_DMA_PORT    DMA1
#define SPI2_TX_DMA_CH      DMA_CH1
#define SPI2_TX_DMA_CH_IRQN DMA1_Channel1_IRQn
#define SPI2_TX_DMA_CH_IRQH DMA1_Channel1_IRQHandler
#else
#error "SPI2_TX_DMA incorrect."
#endif
#else
#define SPI2_TX_DMA_PORT 0
#define SPI2_TX_DMA_CH   0
#endif
#endif
//SPI3
#if SPI3_ENABLE
#if SPI3_RX_DMA_ENABLE || SPI3_TX_DMA_ENABLE
#error "SPI3 dosen't have DMA."
#endif
#endif
/*---------------------------------------------------
 *                   SPI_Object
 *---------------------------------------------------*/
class SPI_Object
{
public:
  SPI_Object(uint32_t SPIx,
             uint32_t RDMA,
             dma_channel_enum RDMA_CH, 
             uint32_t TDMA,
             dma_channel_enum TDMA_CH,
             uint8_t *dma_rx_buffer, int dma_rx_buffer_size,
             uint8_t *dma_tx_buffer, int dma_tx_buffer_size) :
    spi(SPIx),
    rx_dma(RDMA),
    tx_dma(TDMA),
    rx_dma_ch(RDMA_CH),
    tx_dma_ch(TDMA_CH),
    dma_rx_buffer(dma_rx_buffer),
    dma_tx_buffer(dma_tx_buffer),
    dma_rx_buffer_size(dma_rx_buffer_size),
    dma_tx_buffer_size(dma_tx_buffer_size),
    data_bits(8),
    rx_busy(false),
    tx_busy(false)
  {}
  
  uint32_t spi;
  uint32_t rx_dma;
  uint32_t tx_dma;
  dma_channel_enum rx_dma_ch;
  dma_channel_enum tx_dma_ch;
  uint8_t *dma_rx_buffer;
  uint8_t *dma_tx_buffer;
  uint32_t dma_rx_buffer_size;
  uint32_t dma_tx_buffer_size;
  uint8_t data_bits;
  bool rx_busy;
  bool tx_busy;
  
  void dma_rx_config();
  void dma_tx_config();
  void dma_rx_start(uint32_t number);
  void dma_tx_start(uint32_t number);
  void dma_rx_end();
  void dma_tx_end();
  bool config(uint32_t cfg);
  int transfer(uint8_t *tx_buffer, uint8_t *rx_buffer, uint32_t number);
};
/*
*/
void SPI_Object::dma_rx_config()
{ 
  dma_parameter_struct dma_init_struct;
  
  dma_deinit(rx_dma, rx_dma_ch);
  dma_struct_para_init(&dma_init_struct);
  dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_addr = (uint32_t)dma_rx_buffer;
  dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  if(data_bits == 16) {
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
  } else {
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
  }
  dma_init_struct.number = 0;
  dma_init_struct.periph_addr = ((uint32_t)&SPI_DATA(spi));
  dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  dma_init_struct.periph_width = dma_init_struct.memory_width;
  dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
  dma_init(rx_dma, rx_dma_ch, &dma_init_struct);
  
  dma_circulation_disable(rx_dma, rx_dma_ch);
  dma_memory_to_memory_disable(rx_dma, rx_dma_ch);
  
  //Interrupt config
  dma_interrupt_enable(rx_dma, rx_dma_ch, DMA_INT_FTF);
  //Enable spi dma receive  
  spi_dma_enable(spi, SPI_DMA_RECEIVE);
}
/*
*/
void SPI_Object::dma_tx_config()
{
  dma_parameter_struct dma_init_struct;
  
  dma_deinit(tx_dma, tx_dma_ch);
  dma_struct_para_init(&dma_init_struct);
  dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
  dma_init_struct.memory_addr = (uint32_t)dma_tx_buffer;
  dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  if(data_bits == 16) {
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
  } else {
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
  }
  dma_init_struct.number = 0;
  dma_init_struct.periph_addr = ((uint32_t)&SPI_DATA(spi));
  dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  dma_init_struct.periph_width = dma_init_struct.memory_width;
  dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
  dma_init(tx_dma, tx_dma_ch, &dma_init_struct);
  
  dma_circulation_disable(tx_dma, tx_dma_ch);
  dma_memory_to_memory_disable(tx_dma, tx_dma_ch);
  
  //Interrupt config
  dma_interrupt_enable(tx_dma, tx_dma_ch, DMA_INT_FTF);
  //Enable spi dma receive  
  spi_dma_enable(spi, SPI_DMA_TRANSMIT);;
}
/*
*/
void SPI_Object::dma_rx_start(uint32_t number) 
{
  if(number > dma_rx_buffer_size) {
    number = dma_rx_buffer_size;
  }
  
  rx_busy = true;
  dma_transfer_number_config(rx_dma, rx_dma_ch, number);
  dma_channel_enable(rx_dma, rx_dma_ch);
}
/*
*/
void SPI_Object::dma_tx_start(uint32_t number) 
{
  if(number > dma_tx_buffer_size) {
    number = dma_tx_buffer_size;
  }
  
  tx_busy = true;
  dma_transfer_number_config(tx_dma, tx_dma_ch, number);
  dma_channel_enable(tx_dma, tx_dma_ch);
}
/*
*/
void SPI_Object::dma_rx_end()
{
  dma_channel_disable(rx_dma, rx_dma_ch);
  rx_busy = false;
}
/*
*/
void SPI_Object::dma_tx_end()
{
  dma_channel_disable(tx_dma, tx_dma_ch);
  tx_busy = false;
}
/*
*/
bool SPI_Object::config(uint32_t cfg)
{  
  spi_parameter_struct spi_init_struct;
  
  spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
  //mode
  uint32_t tmp = HSPI_CFG_EXTRACT(cfg, MODE);
  if(tmp == HSPI_MODE(MASTER)) {
    spi_init_struct.device_mode          = SPI_MASTER;
  } else {
    spi_init_struct.device_mode          = SPI_SLAVE;
  }
  //data bits
  tmp = HSPI_CFG_EXTRACT(cfg, DATA);
  if(tmp == HSPI_DATA(8B)) {
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
  } else {
    spi_init_struct.frame_size           = SPI_FRAMESIZE_16BIT;
  }
  //cpol cpha
  uint32_t cpol = HSPI_CFG_EXTRACT(cfg, CPOL);
  uint32_t cpha = HSPI_CFG_EXTRACT(cfg, CPHA);
  if(cpol == HSPI_CPOL(HIGH)) {
    if(cpha == HSPI_CPHA(1EDGE)) {
      spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE;
    } else {
      spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
    }
  } else {
    if(cpha == HSPI_CPHA(1EDGE)) {
      spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
    } else {
      spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
    }
  }
  //nss 
  tmp = HSPI_CFG_EXTRACT(cfg, NSS);
  if(tmp == HSPI_NSS(SOFT)) {
    spi_init_struct.nss                  = SPI_NSS_SOFT;	
  } else{
    spi_init_struct.nss                  = SPI_NSS_HARD;
  }
  //first bit 
  tmp = HSPI_CFG_EXTRACT(cfg, FB);
  if(tmp == HSPI_FB(MSB)) {
    spi_init_struct.endian               = SPI_ENDIAN_MSB;	
  } else {
    spi_init_struct.endian               = SPI_ENDIAN_LSB;
  }
  //baud rate prescaler
  tmp = HSPI_CFG_EXTRACT(cfg, BRP);
  spi_init_struct.prescale             = CTL0_PSC(tmp);
  
  spi_i2s_deinit(spi);
  spi_init(spi, &spi_init_struct);
  spi_enable(spi);
  
  return true;
}
/*
*/
int SPI_Object::transfer(uint8_t *tx_buffer, uint8_t *rx_buffer, uint32_t number)
{ 
  //Only in normal mode
  spi_i2s_data_receive(spi);  //clear receive buffer first
  
  if(data_bits == 16) {
    uint16_t *tx = (uint16_t*)tx_buffer;
    uint16_t *rx = (uint16_t*)rx_buffer;
    number /= 2;
    
    if(tx == nullptr) {   //Only read, no matter what send
      for(int i=0; i<number; i++) {
        while(spi_i2s_flag_get(spi, I2S_FLAG_TBE) != RESET);
        spi_i2s_data_transmit(spi, 0);
        while(spi_i2s_flag_get(spi, I2S_FLAG_RBNE) != RESET);
        rx[i] = spi_i2s_data_receive(spi);
      }
    } else if(rx == nullptr) { //Only send, no matter what read
      for(int i=0; i<number; i++) {
        while(spi_i2s_flag_get(spi, I2S_FLAG_TBE) != RESET);
        spi_i2s_data_transmit(spi, tx[i]);
        while(spi_i2s_flag_get(spi, I2S_FLAG_RBNE) != RESET);
        spi_i2s_data_receive(spi);
      }
    } else { //Send and read
      for(int i=0; i<number; i++) {
        while(spi_i2s_flag_get(spi, I2S_FLAG_TBE) != RESET);
        spi_i2s_data_transmit(spi, tx[i]);
        while(spi_i2s_flag_get(spi, I2S_FLAG_RBNE) != RESET);
        rx[i] = spi_i2s_data_receive(spi);
      }
    }
  } else {
    if(tx_buffer == nullptr) {   //Only read, no matter what send
      for(int i=0; i<number; i++) {
        while(spi_i2s_flag_get(spi, I2S_FLAG_TBE) != RESET);
        spi_i2s_data_transmit(spi, 0);
        while(spi_i2s_flag_get(spi, I2S_FLAG_RBNE) != RESET);
        rx_buffer[i] = (uint8_t)spi_i2s_data_receive(spi);
      }
    } else if(rx_buffer == nullptr) { //Only send, no matter what read
      for(int i=0; i<number; i++) {
        while(spi_i2s_flag_get(spi, I2S_FLAG_TBE) != RESET);
        spi_i2s_data_transmit(spi, (uint16_t)tx_buffer[i]);
        while(spi_i2s_flag_get(spi, I2S_FLAG_RBNE) != RESET);
        spi_i2s_data_receive(spi);
      }
    } else { //Send and read
      for(int i=0; i<number; i++) {
        while(spi_i2s_flag_get(spi, I2S_FLAG_TBE) != RESET);
        spi_i2s_data_transmit(spi, (uint16_t)tx_buffer[i]);
        while(spi_i2s_flag_get(spi, I2S_FLAG_RBNE) != RESET);
        rx_buffer[i] = (uint8_t)spi_i2s_data_receive(spi);
      }
    }
  }
    
  return number;
}
/*----------------------------------------
 *             SPI0 Object
 *-----------------------------------------*/
#if SPI0_ENABLE
#if SPI0_RX_DMA_ENABLE
  static uint8_t spi0_rx_dma_buffer[SPI0_RX_DMA_BUFFER_SIZE];
#else
  static uint8_t *spi0_rx_dma_buffer = nullptr;
#endif
#if SPI0_TX_DMA_ENABLE
  static uint8_t spi0_tx_dma_buffer[SPI0_TX_DMA_BUFFER_SIZE];
#else
  static uint8_t *spi0_tx_dma_buffer = nullptr;
#endif
  static SPI_Object spi0(SPI0, 
                         SPI0_RX_DMA_PORT, (dma_channel_enum)SPI0_RX_DMA_CH, 
                         SPI0_TX_DMA_PORT, (dma_channel_enum)SPI0_TX_DMA_CH,
                         spi0_rx_dma_buffer, SPI0_RX_DMA_BUFFER_SIZE,
                         spi0_tx_dma_buffer, SPI0_TX_DMA_BUFFER_SIZE);
#endif
/*----------------------------------------
 *             SPI1 Object
 *-----------------------------------------*/
#if SPI1_ENABLE
#if SPI1_RX_DMA_ENABLE
  static uint8_t spi1_rx_dma_buffer[SPI1_RX_DMA_BUFFER_SIZE];
#else
  static uint8_t *spi1_rx_dma_buffer = nullptr;
#endif
#if SPI1_TX_DMA_ENABLE
  static uint8_t spi1_tx_dma_buffer[SPI1_TX_DMA_BUFFER_SIZE];
#else
  static uint8_t *spi1_tx_dma_buffer = nullptr;
#endif
  static SPI_Object spi1(SPI1, 
                         SPI1_RX_DMA_PORT, (dma_channel_enum)SPI1_RX_DMA_CH, 
                         SPI1_TX_DMA_PORT, (dma_channel_enum)SPI1_TX_DMA_CH,
                         spi1_rx_dma_buffer, SPI1_RX_DMA_BUFFER_SIZE,
                         spi1_tx_dma_buffer, SPI1_TX_DMA_BUFFER_SIZE);
#endif
/*----------------------------------------
 *             SPI2 Object
 *-----------------------------------------*/
#if SPI2_ENABLE
#if SPI2_RX_DMA_ENABLE
  static uint8_t spi2_rx_dma_buffer[SPI2_RX_DMA_BUFFER_SIZE];
#else
  static uint8_t *spi2_rx_dma_buffer = nullptr;
#endif
#if SPI2_TX_DMA_ENABLE
  static uint8_t spi2_tx_dma_buffer[SPI2_TX_DMA_BUFFER_SIZE];
#else
  static uint8_t *spi2_tx_dma_buffer = nullptr;
#endif
  static SPI_Object spi2(SPI2, 
                         SPI2_RX_DMA_PORT, (dma_channel_enum)SPI2_RX_DMA_CH, 
                         SPI2_TX_DMA_PORT, (dma_channel_enum)SPI2_TX_DMA_CH,
                         spi2_rx_dma_buffer, SPI2_RX_DMA_BUFFER_SIZE,
                         spi2_tx_dma_buffer, SPI2_TX_DMA_BUFFER_SIZE);
#endif
  /*----------------------------------------
 *             SPI3 Object
 *-----------------------------------------*/
#if SPI3_ENABLE
  static SPI_Object spi0(SPI0, 
                         0, (dma_channel_enum)0, 
                         0, (dma_channel_enum)0,
                         nullptr, 0,
                         nullptr, 0);
#endif
/*
*/
bool HAL_SPI::init(uint32_t cfg0)
{
  uint8_t rx_nvic_irqn = 0;
  uint8_t tx_nvic_irqn = 0;
  uint8_t nvic_prio = 0;
  
  cfg = cfg0;
  uint32_t tmp = HSPI_CFG_EXTRACT(cfg, DATA);
  if(tmp == HSPI_DATA(8B)) {
    data_bits = 8;
  } else {
    data_bits = 16;
  }
  
  tmp = HSPI_CFG_EXTRACT(cfg, PORT);
  if(tmp == 0) {  //No port
   return false;
  }
#if SPI0_ENABLE
  else if(tmp == HSPI_PORT(0)) {
    spi0.data_bits = data_bits;
    port = (uint32_t)&spi0;
    nvic_prio = NVIC_IRQ_SPI0_PRIORITY;
    //Rx
#if SPI0_RX_DMA_ENABLE
    spi0.dma_rx_config();
    rx_nvic_irqn = SPI0_RX_DMA_CH_IRQN;
#endif
    //Tx
#if SPI0_TX_DMA_ENABLE
    spi0.dma_tx_config();
    tx_nvic_irqn = SPI0_TX_DMA_CH_IRQN;
#endif
  }
#endif
#if SPI1_ENABLE
  else if(tmp == HSPI_PORT(1)) {
    spi1.data_bits = data_bits;
    port = (uint32_t)&spi1;
    nvic_prio = NVIC_IRQ_SPI1_PRIORITY;
    //Rx
#if SPI1_RX_DMA_ENABLE
    spi1.dma_rx_config();
    rx_nvic_irqn = SPI1_RX_DMA_CH_IRQN;
#endif
    //Tx
#if SPI1_TX_DMA_ENABLE
    spi1.dma_tx_config();
    tx_nvic_irqn = SPI1_TX_DMA_CH_IRQN;
#endif
  }
#endif
#if SPI2_ENABLE  
  else if(tmp == SPI_PORT(2)) {
    spi2.data_bits = data_bits;
    port = (uint32_t)&spi2;
    nvic_prio = NVIC_IRQ_SPI2_PRIORITY;
    //Rx
#if SPI2_RX_DMA_ENABLE
    spi2.dma_rx_config();
    rx_nvic_irqn = SPI2_RX_DMA_CH_IRQN;
#endif
    //Tx
#if SPI2_TX_DMA_ENABLE
    spi2.dma_tx_config();
    tx_nvic_irqn = SPI2_TX_DMA_CH_IRQN;
#endif
  }
#endif
#if SPI3_ENABLE 
  else if(tmp == SPI_PORT(3)) {
    spi3.data_bits = data_bits;
    port = (uint32_t)&spi3;
    nvic_prio = NVIC_IRQ_SPI3_PRIORITY;
    //Rx
#if SPI3_RX_DMA_ENABLE
    spi3.dma_rx_config();
    rx_nvic_irqn = SPI3_RX_DMA_CH_IRQN;
#endif
    //Tx
#if SPI3_TX_DMA_ENABLE
    spi3.dma_tx_config();
    tx_nvic_irqn = SPI3_TX_DMA_CH_IRQN;
#endif
  }
#endif
  else if(port == 0) {
    return false;
  }
  
  if(!config(cfg)) {
    return false;
  }
  
  //NVIC config
  //rx
  if(rx_nvic_irqn > 0) {
    nvic_irq_enable(rx_nvic_irqn, nvic_prio, 0U);
  }
  //tx
  if(tx_nvic_irqn > 0) {
    nvic_irq_enable(tx_nvic_irqn, nvic_prio, 0U);
  }
  
  return true;
}
/*
*/
bool HAL_SPI::config(uint32_t cfg0)
{
  cfg &= ~HSPI_CFG_MASK;
  cfg |= cfg0 & HSPI_CFG_MASK;
  return ((SPI_Object*)port)->config(cfg);
}
/*
*/
int HAL_SPI::transfer(uint8_t *tx_buffer, uint8_t *rx_buffer, uint32_t num)
{
  SPI_Object *spi = (SPI_Object*)port;
  if(port) {
    return spi->transfer(tx_buffer, rx_buffer, num);
  } else {
    return -1;
  }
}
/*
*/
int HAL_SPI::read(uint8_t *buffer, uint32_t number)
{
  if(HSPI_CFG_EXTRACT(cfg, WIRE) == HSPI_WIRE(2L1D)) {
    mosi_pin->set_mode(HGPIO_MODE_IN);
  }
  
  SPI_Object *spi = (SPI_Object*)port;
  if(spi->dma_rx_buffer == nullptr) { //normal mode
    return transfer(nullptr, buffer, number);
  } else if(!spi->rx_busy) { //DMA mode, have new data
    memcpy(buffer, spi->dma_rx_buffer, number);
    spi->dma_rx_start(number); //where rx_busy will be set true
    return number;
  }
  
  return 0;
}
/*
*/
int HAL_SPI::write(uint8_t *buffer, uint32_t number)
{
  if(HSPI_CFG_EXTRACT(cfg, WIRE) == HSPI_WIRE(2L1D)) {
    mosi_pin->set_mode(HGPIO_MODE_AF);
  }
  
  SPI_Object *spi = (SPI_Object*)port;
  if(spi->dma_tx_buffer == nullptr) { //normal mode
    return transfer(buffer, nullptr,  number);
  } else if(!spi->tx_busy) {  //DMA mode
    memcpy(spi->dma_tx_buffer, buffer, number);
    spi->dma_tx_start(number); //where tx_busy will be set true
    return number;
  }
  
  return 0;
}
/*------------------------------------------------
 *             IRQHandler
 *------------------------------------------------*/
#ifdef __cplusplus
 extern "C" {
#endif
//SPI0
#if SPI0_ENABLE
//RX
#if SPI0_RX_DMA_ENABLE
void SPI0_RX_DMA_CH_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(dma_interrupt_flag_get(SPI0_RX_DMA_PORT, SPI0_RX_DMA_CH, DMA_INT_FLAG_FTF) != RESET)
  {
    dma_interrupt_flag_clear(SPI0_RX_DMA_PORT, SPI0_RX_DMA_CH, DMA_INT_FLAG_FTF);
    spi0.dma_rx_end();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}   
#endif
//TX
#if SPI0_TX_DMA_ENABLE
void SPI0_TX_DMA_CH_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(dma_interrupt_flag_get(SPI0_TX_DMA_PORT, SPI0_TX_DMA_CH, DMA_INT_FLAG_FTF) != RESET)
  {
    dma_interrupt_flag_clear(SPI0_TX_DMA_PORT, SPI0_TX_DMA_CH, DMA_INT_FLAG_FTF);
    spi0.dma_tx_end();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif
#endif

//SPI1
#if SPI1_ENABLE
//RX
#if SPI1_RX_DMA_ENABLE
void SPI1_RX_DMA_CH_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(dma_interrupt_flag_get(SPI1_RX_DMA_PORT, SPI1_RX_DMA_CH, DMA_INT_FLAG_FTF) != RESET)
  {
    dma_interrupt_flag_clear(SPI1_RX_DMA_PORT, SPI1_RX_DMA_CH, DMA_INT_FLAG_FTF);
    spi1.dma_rx_end();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}   
#endif
//TX
#if SPI1_TX_DMA_ENABLE
void SPI1_TX_DMA_CH_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(dma_interrupt_flag_get(SPI1_TX_DMA_PORT, SPI1_TX_DMA_CH, DMA_INT_FLAG_FTF) != RESET)
  {
    dma_interrupt_flag_clear(SPI1_TX_DMA_PORT, SPI1_TX_DMA_CH, DMA_INT_FLAG_FTF);
    spi1.dma_tx_end();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif
#endif

//SPI2
#if SPI2_ENABLE
//RX
#if SPI2_RX_DMA_ENABLE
void SPI2_RX_DMA_CH_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(dma_interrupt_flag_get(SPI2_RX_DMA_PORT, SPI2_RX_DMA_CH, DMA_INT_FLAG_FTF) != RESET)
  {
    dma_interrupt_flag_clear(SPI2_RX_DMA_PORT, SPI2_RX_DMA_CH, DMA_INT_FLAG_FTF);
    spi2.dma_rx_end();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}   
#endif
//TX
#if SPI2_TX_DMA_ENABLE
void SPI2_TX_DMA_CH_IRQH()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  
  if(dma_interrupt_flag_get(SPI2_TX_DMA_PORT, SPI2_TX_DMA_CH, DMA_INT_FLAG_FTF) != RESET)
  {
    dma_interrupt_flag_clear(SPI2_TX_DMA_PORT, SPI2_TX_DMA_CH, DMA_INT_FLAG_FTF);
    spi2.dma_tx_end();
  }
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
#endif
#endif
/*
*/
#ifdef __cplusplus
}
#endif  
  
  
  
  
  

